Assign functions to variables


In [2]:
def greet(name):
    return "hello " + name

greet_someone = greet
print(greet_someone("John"))


hello John

Define functions inside other functions


In [3]:
def greet(name):
    def get_message():
        return "Hello "

    result = get_message() + name
    return result

print(greet("John"))


Hello John

Functions can be passed as parameters to other functions


In [4]:
def greet(name):
   return "Hello " + name 

def call_func(func):
    other_name = "John"
    return func(other_name)  

print(call_func(greet))


Hello John

Functions can return other functions


In [5]:
def compose_greet_func():
    def get_message():
        return "Hello there!"

    return get_message

greet = compose_greet_func()
print(greet())


Hello there!

Inner functions have access to the enclosing scope


In [6]:
def compose_greet_func(name):
    def get_message():
        return "Hello there " + name + "!"

    return get_message

greet = compose_greet_func("John")
print(greet())


Hello there John!

Decorators


In [7]:
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

my_get_text = p_decorate(get_text)

print(my_get_text("John"))


<p>lorem ipsum, John dolor sit amet</p>

Python's Decorator Syntax


In [8]:
def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print(get_text("John"))


<p>lorem ipsum, John dolor sit amet</p>

What does this new syntax offer?


In [9]:
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

def strong_decorate(func):
    def func_wrapper(name):
        return "<strong>{0}</strong>".format(func(name))
    return func_wrapper

def div_decorate(func):
    def func_wrapper(name):
        return "<div>{0}</div>".format(func(name))
    return func_wrapper

In [10]:
my_get_text = div_decorate(p_decorate(strong_decorate(get_text)))

print(my_get_text("John"))


<div><p><strong>lorem ipsum, John dolor sit amet</strong></p></div>

In [11]:
@div_decorate
@p_decorate
@strong_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print(get_text("John"))


<div><p><strong>lorem ipsum, John dolor sit amet</strong></p></div>

Decorating Methods


In [12]:
def p_decorate(func):
   def func_wrapper(self):
       return "<p>{0}</p>".format(func(self))
   return func_wrapper

class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"

    @p_decorate
    def get_fullname(self):
        return self.name + " " + self.family

my_person = Person()
print(my_person.get_fullname())


<p>John Doe</p>

In [13]:
def p_decorate(func):
   def func_wrapper(*args, **kwargs):
       return "<p>{0}</p>".format(func(*args, **kwargs))
   return func_wrapper

class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"

    @p_decorate
    def get_fullname(self):
        return self.name + " " + self.family

my_person = Person()

print(my_person.get_fullname())


<p>John Doe</p>

Passing arguments to decorators aka decorator generators


In [14]:
def tags(tag_name):
    def tags_decorator(func):
        def func_wrapper(name):
            return "<{0}>{1}</{0}>".format(tag_name, func(name))
        return func_wrapper
    return tags_decorator

@tags("p")
def get_text(name):
    return "Hello " + name

print(get_text("John"))


<p>Hello John</p>

Source examples thanks to Ayman Farhat